package com.example.demo.algorithm.lesson.basic.class2;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 *
 * @author liweizhi
 */
public class ArrayImplements {
    public static class MyStack<E> {
        Object[] arr;
        int size;
        int offset = -1;

        public void push(E element) {
            if (offset == size) {
                return;
            }
            arr[++offset] = element;
        }

        public E pop() {
            if (offset < 0) {
                return null;
            }
            E e = (E) arr[offset--];
            return e;
        }

        public MyStack(int size) {
            this.size = size;
            arr = new Object[size];
        }
    }

    public static class MyQueue<E> {
        Object[] arr;
        int size;
        int length = 0;
        int addIndex = 0;
        int popIndex = 0;

        public boolean offer(E element) {
            if (length == size) {
                return false;
            }
            length++;
            arr[addIndex] = element;
            // addIndex++
            addIndex = nextIndex(addIndex);
            return true;
        }

        public E poll() {
            if (length == 0) {
                return null;
            }
            length--;
            E e = (E) arr[popIndex];
            // popIndex++
            popIndex = nextIndex(popIndex);
            return e;
        }

        private int nextIndex(int index) {
            return index < size - 1 ? index + 1 : 0;
        }

        public MyQueue(int size) {
            this.size = size;
            arr = new Object[size];
        }
    }

    public static void main(String[] args) {
        check();
    }

    private static void check() {
        int testTimes = 10_0000;
        int size = 20;
        int maxValue = 20;
        for (int i = 0; i < testTimes; i++) {
            Stack<Integer> stackT = new Stack<>();
            MyStack<Integer> stack = new MyStack<>(size);
            Queue<Integer> queueT = new LinkedList<>();
            MyQueue<Integer> myQueue = new MyQueue<>(20);
            for (int j = size; j > 0; j--) {
                checkMyStack(maxValue, stackT, stack);
                checkMyQueue(maxValue, queueT, myQueue);
            }
        }
        System.out.printf("finish");
    }

    private static void checkMyStack(int maxValue, Stack<Integer> stackT, MyStack<Integer> stack) {
        int numS = (int) (Math.random() * maxValue);
        if (stackT.empty()) {
            stackT.push(numS);
            stack.push(numS);
            return;
        }
        if (Math.random() > 0.5D) {
            stackT.push(numS);
            stack.push(numS);
        } else {
            Integer popStackT = stackT.pop();
            Integer popMyStack = stack.pop();
            if (!DoubleEndsQueue.isEqual(popStackT, popMyStack)) {
                System.err.println("error!");
            }
        }
    }

    private static void checkMyQueue(int maxValue, Queue<Integer> queueT, MyQueue<Integer> myQueue) {
        int numS = (int) (Math.random() * maxValue);
        if (queueT.isEmpty()) {
            queueT.offer(numS);
            myQueue.offer(numS);
            return;
        }
        if (Math.random() > 0.5D) {
            queueT.offer(numS);
            myQueue.offer(numS);
        } else {
            Integer popT = queueT.poll();
            Integer popMy = myQueue.poll();
            if (!DoubleEndsQueue.isEqual(popT, popMy)) {
                System.err.println("error!");
            }
        }
    }
}
